package com.alibaba.cloud.domain;

import com.alibaba.cloud.application.banktransfer.*;
import org.axonframework.commandhandling.CommandHandler;
import org.axonframework.eventhandling.EventHandler;
import org.axonframework.modelling.command.AggregateIdentifier;
import org.axonframework.spring.stereotype.Aggregate;

import static org.axonframework.modelling.command.AggregateLifecycle.apply;

@Aggregate
public class BankTransferDomain {

	@AggregateIdentifier
	private String bankTransferId;
	private String sourceBankAccountId;
	private String destinationBankAccountId;
	private long amount;
	private Status status;

	protected BankTransferDomain() {
	}

	@CommandHandler
	public BankTransferDomain(CreateBankTransferCommand command) {
		apply(new BankTransferCreatedEvent(command.getBankTransferId(), command.getSourceBankAccountId(),
				command.getDestinationBankAccountId(), command.getAmount()));
	}

	@CommandHandler
	public void handle(MarkBankTransferCompletedCommand command) {
		apply(new BankTransferCompletedEvent(command.getBankTransferId()));
	}

	@CommandHandler
	public void handle(MarkBankTransferFailedCommand command) {
		apply(new BankTransferFailedEvent(command.getBankTransferId()));
	}

	@EventHandler
	public void on(BankTransferCreatedEvent event) throws Exception {
		this.bankTransferId = event.getBankTransferId();
		this.sourceBankAccountId = event.getSourceBankAccountId();
		this.destinationBankAccountId = event.getDestinationBankAccountId();
		this.amount = event.getAmount();
		this.status = Status.STARTED;
	}

	@EventHandler
	public void on(BankTransferCompletedEvent event) {
		this.status = Status.COMPLETED;
	}

	@EventHandler
	public void on(BankTransferFailedEvent event) {
		this.status = Status.FAILED;
	}

	private enum Status {
		STARTED, FAILED, COMPLETED
	}

	public String getBankTransferId() {
		return bankTransferId;
	}

	public void setBankTransferId(String bankTransferId) {
		this.bankTransferId = bankTransferId;
	}

	public String getSourceBankAccountId() {
		return sourceBankAccountId;
	}

	public void setSourceBankAccountId(String sourceBankAccountId) {
		this.sourceBankAccountId = sourceBankAccountId;
	}

	public String getDestinationBankAccountId() {
		return destinationBankAccountId;
	}

	public void setDestinationBankAccountId(String destinationBankAccountId) {
		this.destinationBankAccountId = destinationBankAccountId;
	}

	public long getAmount() {
		return amount;
	}

	public void setAmount(long amount) {
		this.amount = amount;
	}

	public Status getStatus() {
		return status;
	}

	public void setStatus(Status status) {
		this.status = status;
	}

}